package com.itzdm.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itzdm.client.domain.UserSearchDto;
import com.itzdm.common.constant.RedisConstant;
import com.itzdm.common.context.UserContext;
import com.itzdm.common.exception.BadRequestException;
import com.itzdm.common.utils.MinioUtils;
import com.itzdm.user.domain.dto.UserChangeDto;
import com.itzdm.user.domain.dto.UserLoginDto;
import com.itzdm.user.domain.dto.UserPwdChangeDto;
import com.itzdm.user.domain.dto.UserRegisterDto;
import com.itzdm.user.domain.po.User;
import com.itzdm.user.domain.vo.UserChangeVo;
import com.itzdm.user.domain.vo.UserGetVo;
import com.itzdm.user.domain.vo.UserLoginVo;
import com.itzdm.user.domain.vo.UserRegisterVo;
import com.itzdm.user.enums.LoginType;
import com.itzdm.user.mapper.UserMapper;
import com.itzdm.user.service.IUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Set;
import java.util.UUID;

@Service
@RequiredArgsConstructor
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    private final RedisTemplate redisTemplate;

    private static final String FRIEND_LIST_KEY = "friend:list:";

    private final MinioUtils minioUtils;

    /**
     * 用户登录(不同方式)
     *
     * @param userLoginDto
     * @return
     */
    @Override
    public UserLoginVo login(UserLoginDto userLoginDto) {
        LoginType loginType = userLoginDto.getLoginTypeEnum();
        String email = userLoginDto.getEmail();
        String password = userLoginDto.getPassword();
        String code = userLoginDto.getCode();
        String tfId = userLoginDto.getTfId();

        // 根据登录类型和标识查询用户
        User user = switch (loginType) {
            case EMAIL_PASSWORD, EMAIL_CODE -> this.getOne(new QueryWrapper<User>().eq("email", email));
            case TFID_PASSWORD -> this.getOne(new QueryWrapper<User>().eq("tf_id", tfId));
        };

        if (user == null) {
            throw new BadRequestException("用户不存在");
        }

        // 根据登录类型验证
        switch (loginType) {
            case EMAIL_PASSWORD, TFID_PASSWORD -> {
                // 校验密码
                String md5Pwd = DigestUtils.md5DigestAsHex(password.getBytes());
                if (!user.getPassword().equals(md5Pwd)) {
                    throw new BadRequestException("密码错误");
                }
            }
            case EMAIL_CODE -> {
                // 校验验证码
                String redisKey = RedisConstant.EMAIL_CODE + email;
                String redisCode = (String) redisTemplate.opsForValue().get(redisKey);
                if (redisCode == null) {
                    throw new BadRequestException("验证码已过期");
                }
                if (!redisCode.equalsIgnoreCase(code)) {
                    throw new BadRequestException("验证码错误");
                }
                // 验证码正确，删除验证码
                redisTemplate.delete(redisKey);
            }
        }

        // 登录成功，返回用户信息
        UserLoginVo loginVo = new UserLoginVo();
        BeanUtils.copyProperties(user, loginVo);
        return loginVo;
    }

    /**
     * 注册用户
     *
     * @param userRegisterDto
     * @return
     */
    @Override
    public UserRegisterVo register(UserRegisterDto userRegisterDto) {
        String email = userRegisterDto.getEmail();
        String code = userRegisterDto.getCode();
        String password = userRegisterDto.getPassword();
        // 校验邮箱是否已注册
        User existingUser = this.getOne(new QueryWrapper<User>().eq("email", email));
        if (existingUser != null) {
            throw new BadRequestException("邮箱已注册");
        }
        // 校验验证码
        String redisKey = RedisConstant.EMAIL_CODE + email;
        String redisCode = (String) redisTemplate.opsForValue().get(redisKey);
        if (redisCode == null) {
            throw new BadRequestException("验证码已过期");
        }
        if (!redisCode.equalsIgnoreCase(code)) {
            throw new BadRequestException("验证码错误");
        }
        // 创建新用户
        User newUser = new User();
        newUser.setEmail(email);
        // 对密码进行加密
        String md5Pwd = DigestUtils.md5DigestAsHex(password.getBytes());
        newUser.setPassword(md5Pwd);
        String tfId = UUID.randomUUID().toString();
        newUser.setTfId(tfId);
        String nickname = "tf" + tfId.substring(0, 8);
        newUser.setNickname(nickname);
        newUser.setAvatar("default_avatar.png");
        newUser.setGender(0);
        this.save(newUser);
        // 注册成功，删除验证码
        redisTemplate.delete(redisKey);
        // 返回注册成功的用户信息
        UserRegisterVo registerVo = new UserRegisterVo();
        BeanUtils.copyProperties(newUser, registerVo);
        return registerVo;
    }

    /**
     * 修改密码
     *
     * @param userPwdChangeDto
     */
    @Override
    public void changePassword(UserPwdChangeDto userPwdChangeDto) {
        String email = userPwdChangeDto.getEmail();
        String code = userPwdChangeDto.getCode();
        String newPassword = userPwdChangeDto.getNewPassword();

        // 查询用户是否存在
        User user = this.getOne(new QueryWrapper<User>().eq("email", email));
        if (user == null) {
            throw new BadRequestException("用户不存在");
        }
        // 校验验证码
        String redisKey = RedisConstant.EMAIL_CODE + email;
        String redisCode = (String) redisTemplate.opsForValue().get(redisKey);
        if (redisCode == null) {
            throw new BadRequestException("验证码已过期");
        }
        if (!redisCode.equalsIgnoreCase(code)) {
            throw new BadRequestException("验证码错误");
        }
        // 全部校验完成，修改密码
        String md5Pwd = DigestUtils.md5DigestAsHex(newPassword.getBytes());
        user.setPassword(md5Pwd);
        user.setUpdateTime(LocalDateTime.now());
        this.updateById(user);
    }

    /**
     * 修改用户信息
     *
     * @param userChangeDto
     * @return
     */
    @Override
    public UserChangeVo changeUserInfo(UserChangeDto userChangeDto) {
        Long userId = UserContext.getUser();
        String nickname = userChangeDto.getNickname();
        Integer gender = userChangeDto.getGender();
        String avatar = userChangeDto.getAvatar();
        String tfId = userChangeDto.getTfId();
        Integer searchEnabled = userChangeDto.getSearchEnabled();
        String signature = userChangeDto.getSignature();
        // 查询用户是否存在
        User user = this.getOne(new QueryWrapper<User>().eq("id", userId));
        if (user == null) {
            throw new BadRequestException("用户不存在");
        }

        // 检查是否修改了关键信息（需要更新好友缓存）
        boolean needUpdateFriendCache = false;

        // 如果修改tfId，需要检查是否已被使用
        if (tfId != null && !tfId.equals(user.getTfId())) {
            User existingUser = this.getOne(new QueryWrapper<User>().eq("tf_id", tfId));
            if (existingUser != null) {
                throw new BadRequestException("TF号已被使用");
            }
            user.setTfId(tfId);
            needUpdateFriendCache = true;
        }

        // 更新其他信息
        if (nickname != null && !nickname.equals(user.getNickname())) {
            user.setNickname(nickname);
            needUpdateFriendCache = true;
        }

        if (gender != null && !gender.equals(user.getGender())) {
            user.setGender(gender);
            needUpdateFriendCache = true;
        }

        if (avatar != null && !avatar.equals(user.getAvatar())) {
            user.setAvatar(avatar);
            needUpdateFriendCache = true;
        }

        if (searchEnabled != null) {
            if (searchEnabled != 0 && searchEnabled != 1) {
                throw new BadRequestException("搜索权限只能为0或1");
            }
            user.setSearchEnabled(searchEnabled);
        }

        if (signature != null && !signature.equals(user.getSignature())) {
            user.setSignature(signature);
            needUpdateFriendCache = true;
        }

        user.setUpdateTime(LocalDateTime.now());
        // 更新用户信息
        this.updateById(user);

        // 如果修改了关键信息，删除缓存
        if (needUpdateFriendCache) {
            String friendPattern = FRIEND_LIST_KEY + "*";
            Set<String> keys = redisTemplate.keys(friendPattern);
            if (keys != null && !keys.isEmpty()) {
                redisTemplate.delete(keys);
                log.info("用户信息已更新，删除所有相关好友列表缓存，共{}个", keys.size());
            } else {
                log.info("用户信息已更新，但未找到相关好友缓存，userId={}", userId);
            }
        }
        // 返回更新后的用户信息
        UserChangeVo changeVo = new UserChangeVo();
        BeanUtils.copyProperties(user, changeVo);
        return changeVo;
    }

    @Override
    public UserGetVo getUserInfo() {
        Long userId = UserContext.getUser();
        // 查询用户信息
        User user = this.getOne(new QueryWrapper<User>().eq("id", userId));
        if (user == null) {
            throw new BadRequestException("用户不存在");
        }
        // 返回用户信息
        UserGetVo userGetVo = new UserGetVo();
        BeanUtils.copyProperties(user, userGetVo);
        return userGetVo;
    }

    @Override
    public UserSearchDto getUserInfoByKeyword(String keyword) {
        // 查询用户信息
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<User>()
                .eq(User::getEmail, keyword)
                .or()
                .eq(User::getTfId, keyword);
        User user = this.getOne(queryWrapper);
        if (user != null) {
            UserSearchDto userSearchDto = new UserSearchDto();
            BeanUtils.copyProperties(user, userSearchDto);
            return userSearchDto;
        }
        // 如果没有找到用户，返回null
        return null;
    }

    @Override
    public UserSearchDto getUserInfoById(Long userId) {
        // 查询用户信息
        User user = this.getOne(new QueryWrapper<User>().eq("id", userId));
        if (user != null) {
            UserSearchDto userSearchDto = new UserSearchDto();
            BeanUtils.copyProperties(user, userSearchDto);
            return userSearchDto;
        }
        // 如果没有找到用户，返回null
        return null;
    }

    /**
     * 上传头像
     *
     * @param file
     * @return
     */
    @Override
    public String uploadAvatar(MultipartFile file) {
        Long currentUserId = UserContext.getUser();
        // 根据id查询用户
        User currentUser = getById(currentUserId);
        if (currentUser == null) {
            throw new BadRequestException("用户不存在");
        }
        // 检查文件类型
        String contentType = file.getContentType();
        if (contentType == null || !contentType.startsWith("image/")) {
            throw new BadRequestException("头像只能是图片格式");
        }
        // 删除旧头像
//        String oldAvatar = currentUser.getAvatar();
//        if (oldAvatar != null && !oldAvatar.equals("default_avatar.png")) {
//            try {
//                minioUtils.deleteFile(oldAvatar);
//            } catch (Exception e) {
//                log.error("删除旧头像失败", e);
//            }
//        }
        // 实现minio上传头像
        String fileUrl;
        try {
            fileUrl = minioUtils.uploadFile(file);
        } catch (Exception e) {
            log.error("上传头像失败", e);
            throw new BadRequestException("上传头像失败");
        } finally {
            try {
                if (file != null) {
                    file.getInputStream().close();
                }
            } catch (IOException e) {
                log.error("关闭文件流失败", e);
            }
        }
        return fileUrl;
    }
}